import numpy as np
import generate_chrom_po_p95
import po_p95_explainer
import po_p95_GA_operators
import numpy_basic_operators
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  


# 生成一个初始的合法染色体种群
variable_num = 18
pop_size = 20
next_generate_method = 4
chrom_format = [variable_num - 1, variable_num, pop_size]
legal_chrom = np.empty((0, variable_num))

while legal_chrom.shape[0] < pop_size * 2:
    original_chrom = generate_chrom_po_p95.generate_chrom(pop_size, variable_num)
    temp_legal_chrom = po_p95_explainer.restriction_function(original_chrom, variable_num)
    legal_chrom = np.vstack((legal_chrom, temp_legal_chrom))
    legal_chrom = np.unique(legal_chrom, axis=0)

weight = np.array([0.3, 0.3, 0.4])
legal_chrom = np.int16(legal_chrom)
legal_chrom_with_objective = po_p95_explainer.get_objective_value(legal_chrom, 'geneCode.txt', weight)
current_chrom, chrom_left = po_p95_GA_operators.chose_operator(legal_chrom_with_objective, chrom_format, 1, pop_size)
best_performance_list = []  # 用于存储每次迭代的最优值
worst_performance_list = []  # 用于存储每次迭代的最差值
average_performance_list = []  # 用于存储每次迭代的平均值

if next_generate_method == 4:
    for iter_times in range(101):
        chrom_better, chrom_worse = po_p95_GA_operators.chose_operator(current_chrom, chrom_format, 2)
        chrom_to_keep, _ = po_p95_GA_operators.chose_operator(current_chrom, chrom_format, 1, np.int16(pop_size / 10))
        check_unique = chrom_to_keep[:, 0:variable_num]
        mutate_possibility = 0.5
        child_from_Cross_better = np.empty((0, variable_num))
        child_from_cross_hybrid_and_mutate = np.empty((0, variable_num))
        child_from_initialization = np.empty((0, variable_num))

        # 较优种群内部交叉
        while child_from_Cross_better.shape[0] < pop_size * 0.5:
            num_new_from_better = pop_size / 2
            chrom_better_A = chrom_better[:np.int16(num_new_from_better / 2), :]
            chrom_better_B = chrom_better[np.int16(num_new_from_better / 2):, :]
            crossed_chrom_better = po_p95_GA_operators.cross_operator(chrom_better_A, chrom_better_B, chrom_format)
            filtered_child = numpy_basic_operators.delete_identical_lines(check_unique, crossed_chrom_better, 1)

            # 确保 filtered_child 的形状正确
            if filtered_child.shape[0] == 0:
                continue

            # 确保 filtered_child 的内容是整数
            filtered_child = np.int16(filtered_child)

            # 确保 filtered_child 没有重复的行
            filtered_child = np.unique(filtered_child, axis=0)

            crossed_chrom_better_legal = po_p95_explainer.restriction_function(filtered_child, variable_num)
            child_from_Cross_better = np.vstack((child_from_Cross_better, crossed_chrom_better_legal))

        temp_indices = np.random.choice(child_from_Cross_better.shape[0], np.int16(pop_size * 0.5), False)
        child_from_Cross_better = child_from_Cross_better[temp_indices, :]
        check_unique = np.vstack((check_unique, child_from_Cross_better))

        # 较优-较差种群混合交叉和变异
        while child_from_cross_hybrid_and_mutate.shape[0] < pop_size * 0.4:
            crossed_chrom = po_p95_GA_operators.cross_operator(chrom_better, chrom_worse, chrom_format)
            mutate_indv_indices = np.random.choice(chrom_worse.shape[0], np.int16(chrom_worse.shape[0] * mutate_possibility), False)
            indv_to_mutate = chrom_worse[mutate_indv_indices, :]
            mutated_chrom = po_p95_GA_operators.mutate_operator(indv_to_mutate, chrom_format, mutate_pos_num=1)
            temp_child_chrom = np.vstack((crossed_chrom, mutated_chrom))
            filtered_temp_child_chrom = np.unique(temp_child_chrom, axis=0)
            filtered_temp_child_chrom = numpy_basic_operators.delete_identical_lines(check_unique, filtered_temp_child_chrom, 1)

            # 确保 filtered_temp_child_chrom 的形状正确
            if filtered_temp_child_chrom.shape[0] == 0:
                continue

            # 确保 filtered_temp_child_chrom 的内容是整数
            filtered_temp_child_chrom = np.int16(filtered_temp_child_chrom)

            # 确保 filtered_temp_child_chrom 没有重复的行
            filtered_temp_child_chrom = np.unique(filtered_temp_child_chrom, axis=0)

            temp_legal_child_chrom = po_p95_explainer.restriction_function(filtered_temp_child_chrom, variable_num)
            child_from_cross_hybrid_and_mutate = np.vstack((child_from_cross_hybrid_and_mutate, temp_legal_child_chrom))

        temp_indices = np.random.choice(child_from_cross_hybrid_and_mutate.shape[0], np.int16(pop_size * 0.4), False)
        child_from_cross_hybrid_and_mutate = child_from_cross_hybrid_and_mutate[temp_indices, :]

        # 初始化种群的手段产生
        while child_from_initialization.shape[0] < pop_size * 0.1:
            original_chrom = generate_chrom_po_p95.generate_chrom(np.int16(pop_size * 0.1), variable_num)
            temp_legal_chrom = po_p95_explainer.restriction_function(original_chrom, variable_num)
            child_from_initialization = np.vstack((child_from_initialization, temp_legal_chrom))

        child_chrom = np.vstack((child_from_Cross_better, child_from_cross_hybrid_and_mutate, child_from_initialization))
        child_chrom = np.int16(child_chrom)
        child_chrom_with_objective = po_p95_explainer.get_objective_value(child_chrom, 'geneCode.txt', weight)
        current_chrom = np.vstack((chrom_to_keep, child_chrom_with_objective))

        best_performance = np.min(current_chrom[:, chrom_format[1]])
        worst_performance = np.max(current_chrom[:, chrom_format[1]])
        average_performance = np.mean(current_chrom[:, chrom_format[1]])

        best_performance_list.append(best_performance)
        worst_performance_list.append(worst_performance)
        average_performance_list.append(average_performance)

        if iter_times % 10 == 0:
            print(current_chrom)
        else:
            pass
        print(iter_times)
        print(f"Best Performance: {best_performance}")

# 绘制适应度变化趋势图
plt.figure(figsize=(10, 6))
plt.plot(range(101), best_performance_list, label='最优适应度', color='red')
plt.plot(range(101), worst_performance_list, label='最差适应度', color='blue')
plt.plot(range(101), average_performance_list, label='平均适应度', color='green')
plt.xlabel('代数')
plt.ylabel('适应度')
plt.title('适应度变化趋势')
plt.legend()
plt.ylim(0, 20)  # 适当扩大 y 轴区间
plt.xlim(0, 100)
plt.show()
